﻿using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using System.Xml;
using System.Text;
using System.Diagnostics;
using System.Web.Caching;
using System.Security.Cryptography;
using System.Xml.Serialization;
using System.Configuration;

namespace AutoUpdater
{
    /// <summary>
    /// Update 的摘要说明
    /// </summary>
    public class Update : IHttpHandler
    {
        private static XmlSerializer xmlSerializer = new XmlSerializer(typeof(UpdateInfo[]));
        private static readonly Guid cacheId = Guid.NewGuid();

        public void ProcessRequest(HttpContext context)
        {
            if (String.Equals(context.Request.RequestType, "GET", StringComparison.OrdinalIgnoreCase))
            {
                string filename = context.Request.QueryString["download"];
                UpdateInfoSection updateInfoSection = GetUpdateConfig();

                if (String.IsNullOrEmpty(filename))
                {
                    context.Response.ContentEncoding = Encoding.UTF8;
                    context.Response.ContentType = "text/xml";

                    MemoryStream stream = context.Cache[cacheId.ToString()] as MemoryStream;

                    if (stream == null)
                    {
                        stream = new MemoryStream();
                        List<string> fileNames = new List<string>();
                        foreach (UpdateInfo update in updateInfoSection.UpdateFiles.Values)
                        {
                            fileNames.Add(update.Path);
                            switch (update.VersionType)
                            {
                                case VersionType.FileVersion:
                                    update.Version = FileVersionInfo.GetVersionInfo(update.Path).FileVersion;
                                    break;
                                case VersionType.MD5:
                                    using (FileStream file = File.OpenRead(update.Path)) update.Version = Convert.ToBase64String(MD5.Create().ComputeHash(file));
                                    break;
                            }
                        }

                        xmlSerializer.Serialize(new XmlTextWriter(stream, Encoding.UTF8), new List<UpdateInfo>(updateInfoSection.UpdateFiles.Values).ToArray());
                        context.Cache.Insert(cacheId.ToString(), stream, new CacheDependency(fileNames.ToArray()));
                    }

                    stream.Seek(0, SeekOrigin.Begin);
                    stream.WriteTo(context.Response.OutputStream);
                }
                else
                {
                    UpdateInfo update;
                    if (updateInfoSection.UpdateFiles.TryGetValue(filename, out update))
                    {
                        context.Response.ContentEncoding = Encoding.UTF8;
                        context.Response.ContentType = "application/x-msdownload";
                        context.Response.AppendHeader("Content-Disposition", "attachment;filename=" + filename);
                        context.Response.WriteFile(update.Path);
                    }
                    else
                    {
                        context.Response.ContentEncoding = Encoding.UTF8;
                        context.Response.ContentType = "text/html";
                        context.Response.Output.WriteLine("File {0} not fount.", filename);
                    }

                }
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        private UpdateInfoSection GetUpdateConfig()
        {
            return (UpdateInfoSection)ConfigurationManager.GetSection("UpdateInfos"); ;
        }
    }
}